home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / mosaic / mosaic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  7.1 KB  |  433 lines

  1. /*
  2.  * mosaic.c
  3.  * kirk johnson
  4.  * october 1990
  5.  */
  6.  
  7. #include "mosaic.h"
  8. #include <X11/Xos.h>
  9. #include <pwd.h>
  10.  
  11. #ifdef LOGGING
  12. static FILE *logfile;
  13. static void  OpenLogFile();
  14. #endif
  15.  
  16. Word tile[NTiles];        /* the board */
  17. Word piece[NPieces];        /* the "deck" of pieces */
  18. Word nextpiece;            /* index into the deck */
  19.  
  20. Word size[NTiles];        /* score data structures */
  21. Word parent[NTiles];
  22.  
  23. Word tscore[3];            /* total score */
  24. Word pscore[3];            /* last piece score */
  25. Word remain[3];            /* tiles remaining */
  26.  
  27. NameAndScore highscore[NHighScores];
  28. short UseHighScore = 1;
  29.  
  30.  
  31. main(argc, argv)
  32.      int    argc;
  33.      char **argv;
  34. {
  35.   ReadHighScores();
  36.   InitGame();
  37.   InitDisplay(argc, argv);
  38. #ifdef LOGGING
  39.   OpenLogFile();
  40. #endif
  41.   MainLoop();
  42. }
  43.  
  44.  
  45. void InitGame()
  46. {
  47.   int i, j, k, l;
  48.   int idx, swap;
  49.  
  50.   /* randomize */
  51.   srand48((long)time((long *)0));
  52.  
  53.   /* clear the board */
  54.   for (i=0; i<NTiles; i++)
  55.     tile[i] = 0;
  56.  
  57.   /* set up deck */
  58.   idx = 0;
  59.   for (i=1; i<=3; i++)
  60.     for (j=1; j<=3; j++)
  61.       for (k=1; k<=3; k++)
  62.     for (l=1; l<=3; l++)
  63.       piece[idx++] = (i<<6) | (j<<4) | (k<<2) | (l<<0);
  64.   
  65.   /* shuffle */
  66.   for (i=0; i<1000; i++)
  67.   {
  68.     idx  = lrand48() % NPieces;
  69.     swap = piece[idx];
  70.     piece[idx] = piece[0];
  71.     piece[0]   = swap;
  72.   }
  73.   nextpiece = 0;
  74.  
  75.   /* clear score data structures */
  76.   for (i=0; i<NTiles; i++)
  77.   {
  78.     size[i]   = 1;
  79.     parent[i] = i;
  80.   }
  81.  
  82.   for (i=0; i<3; i++)
  83.   {
  84.     tscore[i] = 0;
  85.     pscore[i] = 0;
  86.     remain[i] = (NPieces * 4) / 3;
  87.   }
  88. }
  89.  
  90.  
  91. void QuitGame()
  92. {
  93.   exit(0);
  94. }
  95.  
  96.  
  97. int DropPiece(r, c, p)
  98.      int  r, c;
  99.      Word p;
  100. {
  101.   int  idx;
  102.   Word type;
  103.   Word nscore[3];
  104.  
  105.   idx = r * BoardSize + c;
  106.   
  107.   /* check for illegal move */
  108.   if ((tile[idx] != 0) ||
  109.       (tile[idx+1] != 0) ||
  110.       (tile[idx+BoardSize] != 0) ||
  111.       (tile[idx+BoardSize+1] != 0))
  112.     return 0;
  113.  
  114.   /* place the piece */
  115.   type = p & 0x03;
  116.   tile[idx] = type;
  117.   remain[type-1] -= 1;
  118.   p >>= 2;
  119.  
  120.   type = p & 0x03;
  121.   tile[idx+1] = type;
  122.   remain[type-1] -= 1;
  123.   p >>= 2;
  124.  
  125.   type = p & 0x03;
  126.   tile[idx+BoardSize] = type;
  127.   remain[type-1] -= 1;
  128.   p >>= 2;
  129.  
  130.   type = p & 0x03;
  131.   tile[idx+BoardSize+1] = p & 0x03;
  132.   remain[type-1] -= 1;
  133.  
  134.   /* update the score */
  135.   UpdateAndScore(r, c, nscore);
  136.   for (idx=0; idx<3; idx++)
  137.   {
  138.     pscore[idx] = nscore[idx] - tscore[idx];
  139.     tscore[idx] = nscore[idx];
  140.   }
  141.  
  142.   /* redraw */
  143.   drawTile(r++, c);
  144.   drawTile(r, c++);
  145.   drawTile(r--, c);
  146.   drawTile(r, c--);
  147.   drawController();
  148.   drawScore();
  149.  
  150.   return 1;
  151. }
  152.  
  153.  
  154. void UpdateAndScore(r, c, score)
  155.      int  r, c;
  156.      Word score[];
  157. {
  158.   int i;
  159.  
  160.   i = r * BoardSize + c;
  161.  
  162.   PossiblyMerge(i, i+1);
  163.   PossiblyMerge(i+BoardSize, i+BoardSize+1);
  164.  
  165.   PossiblyMerge(i, i+BoardSize);
  166.   PossiblyMerge(i+1, i+BoardSize+1);
  167.  
  168.   if (c >= 1)
  169.   {
  170.     PossiblyMerge(i, i-1);
  171.     PossiblyMerge(i+BoardSize, i+BoardSize-1);
  172.   }
  173.  
  174.   if (r >= 1)
  175.   {
  176.     PossiblyMerge(i, i-BoardSize);
  177.     PossiblyMerge(i+1, i-BoardSize+1);
  178.   }
  179.  
  180.   if (c <= (BoardSize-3))
  181.   {
  182.     PossiblyMerge(i+1, i+2);
  183.     PossiblyMerge(i+BoardSize+1, i+BoardSize+2);
  184.   }
  185.  
  186.   if (r <= (BoardSize-3))
  187.   {
  188.     PossiblyMerge(i+BoardSize, i+(2*BoardSize));
  189.     PossiblyMerge(i+BoardSize+1, i+(2*BoardSize)+1);
  190.   }
  191.  
  192.   /* compute the new score */
  193.   for (i=0; i<3; i++)
  194.     score[i] = 0;
  195.   for (i=0; i<NTiles; i++)
  196.     if ((tile[i] != 0) && (parent[i] == i))
  197.       score[tile[i]-1] += size[i] * size[i];
  198. }
  199.  
  200.  
  201. void PossiblyMerge(i, j)
  202.      int i, j;
  203. {
  204.   Word irep;
  205.   Word jrep;
  206.   Word scan;
  207.  
  208.   /* tiles are not the same color */
  209.   if (tile[i] != tile[j]) return;
  210.  
  211.   /* find i's rep */
  212.   irep = i;
  213.   while (parent[irep] != irep)
  214.     irep = parent[irep];
  215.  
  216.   /* compress path from i to irep */
  217.   scan = i;
  218.   while (parent[scan] != scan)
  219.   {
  220.     scan = parent[scan];
  221.     parent[scan] = irep;
  222.   }
  223.  
  224.   /* find j's rep */
  225.   jrep = j;
  226.   while (parent[jrep] != jrep)
  227.     jrep = parent[jrep];
  228.  
  229.   /* compress path from j to jrep */
  230.   scan = j;
  231.   while (parent[scan] != scan)
  232.   {
  233.     scan = parent[scan];
  234.     parent[scan] = jrep;
  235.   }
  236.  
  237.   /* tiles are already in the same set */
  238.   if (irep == jrep) return;
  239.  
  240.   /* merge the sets */
  241.   if (size[irep] > size[jrep])
  242.   {
  243.     parent[jrep] = irep;
  244.     size[irep]  += size[jrep];
  245.   }
  246.   else
  247.   {
  248.     parent[irep] = jrep;
  249.     size[jrep]  += size[irep];
  250.   }
  251. }
  252.  
  253.  
  254. void AutoPlay()
  255. {
  256.   int r, c;
  257.  
  258.   while (nextpiece < NPieces)
  259.   {
  260.     do
  261.     {
  262.       r = lrand48() % (BoardSize-1);
  263.       c = lrand48() % (BoardSize-1);
  264.     }
  265.     while (!DropPiece(r, c, piece[nextpiece]));
  266.     
  267.     nextpiece += 1;
  268.     drawNext();
  269.  
  270.     if (UseHighScore && (nextpiece == NPieces))
  271.       CheckHighScore();
  272.   }
  273. }
  274.  
  275.  
  276. void ReadHighScores()
  277. {
  278.   int   i;
  279.   FILE *s;
  280.  
  281.   s = fopen(ScoreFile, "r");
  282.   if (s == NULL)
  283.   {
  284.     warning("unable to open score file; attempting to create new one");
  285.  
  286.     for (i=0; i<NHighScores; i++)
  287.     {
  288.       strcpy(highscore[i].uname, ".");
  289.       highscore[i].score = -1;
  290.     }
  291.  
  292.     s = fopen(ScoreFile, "w");
  293.     if (s == NULL) {
  294.       warning("unable to create score file");
  295.       UseHighScore = 0;
  296.     }
  297.     else {
  298.       WriteHighScores();
  299.       fclose(s);
  300.  
  301.       if (chmod(ScoreFile, 0777) != 0)
  302.       {
  303.         unlink(ScoreFile);
  304.         fatal("unable to set score file mode");
  305.       }
  306.     }
  307.   }
  308.   else
  309.   {
  310.     for (i=0; i<NHighScores; i++)
  311.       if (fscanf(s, "%s %d",
  312.          highscore[i].uname, &highscore[i].score) != 2)
  313.     fatal("incomplete score file read");
  314.     fclose(s);
  315.   }
  316. }
  317.  
  318.  
  319. void WriteHighScores()
  320. {
  321.   int   i;
  322.   FILE *s;
  323.   
  324.   s = fopen(ScoreFile, "w");
  325.   if (s == NULL) {
  326.     warning("unable to open score file");
  327.     UseHighScore = 0;
  328.   }
  329.   else {
  330.     for (i=0; i<NHighScores; i++)
  331.       fprintf(s, "%s %d\n", highscore[i].uname, highscore[i].score);
  332.   }
  333.   fclose(s);
  334. }
  335.  
  336.  
  337. void CheckHighScore()
  338. {
  339.   int   i;
  340.   int   score;
  341.   char *uname;
  342.  
  343.   uname = getpwuid(getuid())->pw_name;
  344.   score = tscore[0] + tscore[1] + tscore[2];
  345.  
  346.   /*
  347.    * note that we don't actually try to do any locking of
  348.    * the high score file during this critical section ...
  349.    */
  350.  
  351.   ReadHighScores();
  352.   
  353.   for (i=0; i<NHighScores; i++)
  354.     if (strcmp(highscore[i].uname, uname) == 0)
  355.       break;
  356.  
  357.   if (i == NHighScores)
  358.     i = NHighScores - 1;
  359.  
  360.   if (score > highscore[i].score)
  361.   {
  362.     while ((i > 0) && (score > highscore[i-1].score))
  363.     {
  364.       strcpy(highscore[i].uname, highscore[i-1].uname);
  365.       highscore[i].score = highscore[i-1].score;
  366.       i -= 1;
  367.     }
  368.     strcpy(highscore[i].uname, uname);
  369.     highscore[i].score = score;
  370.  
  371.     WriteHighScores();
  372.   }
  373.   
  374.   drawHighScores();
  375.  
  376. #ifdef LOGGING
  377.   /*
  378.    * because we don't catch this and die when we open the file; add
  379.    * the check here. ah well.
  380.    */
  381.   if (logfile != NULL)
  382.   {
  383.     putc(1, logfile);
  384.     fflush(logfile);
  385.   }
  386. #endif
  387. }
  388.  
  389.  
  390. warning(msg)
  391.      char *msg;
  392. {
  393.   fflush(stdout);
  394.   fprintf(stderr, "%s: warning! %s\n", AppName, msg);
  395.   fflush(stderr);
  396. }
  397.  
  398.  
  399. fatal(msg)
  400.      char *msg;
  401. {
  402.   fflush(stdout);
  403.   fprintf(stderr, "%s: %s\n", AppName, msg);
  404.   exit(1);
  405. }
  406.  
  407.  
  408. #ifdef LOGGING
  409. static void OpenLogFile()
  410. {
  411.   char  hostname[256];
  412.   char  logname[256];
  413.  
  414.   if (gethostname(hostname, 256) != 0)
  415.   {
  416. #ifdef DEBUG
  417.     warning("unable to get hostname");
  418. #endif      
  419.     return;
  420.   }
  421.   
  422.   sprintf(logname, "%s/%08X.%s.%d", LogDir, time(NULL), hostname, getuid());
  423.   logfile = fopen(logname, "w");
  424.   if (logfile == NULL)
  425.   {
  426. #ifdef DEBUG
  427.     warning("problems opening logfile");
  428. #endif      
  429.     return;
  430.   }
  431. }
  432. #endif
  433.